package wiiusej.motionAlgorithms;

import java.io.IOException;
import java.util.Vector;

import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.Priority;
import org.apache.log4j.PropertyConfigurator;

import wiiusej.apptest.statistics.AccelerationPaquet;

public class Centroid {

	//Logger
	private static Logger fileLogger;
	private final String fileURL = "src/logs/java/wiiusej/apptest/statistics/Kmeans/Centroids.log";
	
	private CentroidsEnum centroidTypes;

	private Double varXCenter, oldVarXCenter;
	private Double varYCenter, oldVarYCenter;
	private Double varZCenter, oldVarZCenter;
	private Double packetMeanCenter, oldPacketMeanCenter;
	
	private final CentroidsEnum initType;
	
	private Vector<AccelerationPaquet> motionSamples = new Vector<AccelerationPaquet>();  
	
	
	public Centroid(CentroidsEnum centroidType){
		this.initType = centroidType;
		
		PropertyConfigurator.configure("log4j.properties");
		fileLogger = Logger.getLogger("centroid");
		
		PatternLayout pattern1 = 
			new PatternLayout("%m%n");
		
		
		FileAppender fileAppender;
		
		
		try {
			fileAppender = new FileAppender(pattern1,fileURL + "_" + this.initType + ".log");
			fileAppender.setThreshold(Priority.DEBUG);			
			fileLogger.addAppender(fileAppender);
		} catch (IOException e) {
			
			e.printStackTrace();
		}		
		initParameters();
	}


	private void initParameters(){
			
		switch(initType){
			
		case SLOW:
				setAllParameters(centroidTypes.SLOW.getPacketAverage(), centroidTypes.SLOW.getVarX(),
						centroidTypes.SLOW.getVarY(), centroidTypes.SLOW.getVarZ());			
			break;
			
		case BIG:
			setAllParameters(centroidTypes.BIG.getPacketAverage(), centroidTypes.BIG.getVarX(),
					centroidTypes.BIG.getVarY(), centroidTypes.BIG.getVarZ());
			break;
		
		case ROBOTIC:
			setAllParameters(centroidTypes.ROBOTIC.getPacketAverage(), centroidTypes.ROBOTIC.getVarX(),
					centroidTypes.ROBOTIC.getVarY(), centroidTypes.ROBOTIC.getVarZ());
			break;
		
		}
		
		
	}
	
	
	
	public void computeNewCenter(){
		
		if(motionSamples.isEmpty()){
			fileLogger.debug("");
			fileLogger.debug("No MotionSamples to Compute");
			//center remains equal			
		}else{
			
			//the new center will be the mean of all the motion sample contained in this 
			//centroid
			
			double newVarXCenter=0, newVarYCenter=0, newVarZCenter=0, newPacketMeanCenter=0;
			int counter = 0; 
			
			fileLogger.debug("");		
			fileLogger.debug("Computing New Centers: " + this.initType);
			
			
			for(AccelerationPaquet i : motionSamples){
				newPacketMeanCenter = newPacketMeanCenter + i.getCounter();
				newVarXCenter = newVarXCenter + i.getxVar();
				newVarYCenter = newVarYCenter + i.getyVar();
				newVarZCenter = newVarZCenter + i.getzVar();
				counter++;
			}
			
			
			//move current centers to old centers
			oldPacketMeanCenter = packetMeanCenter.doubleValue();
			oldVarXCenter = varXCenter.doubleValue();
			oldVarYCenter = varYCenter.doubleValue();
			oldVarZCenter = varZCenter.doubleValue();
			
			//upload centers
			packetMeanCenter = newPacketMeanCenter/counter;
			varXCenter = newVarXCenter/counter;
			varYCenter = newVarYCenter/counter;
			varZCenter = newVarZCenter/counter;
			
			fileLogger.debug("Center: " + toString());
			fileLogger.info("OLD_Center: " + toString());
		}
		
	}
	
	public boolean sameCenter(){
		
		if( (packetMeanCenter.doubleValue()==oldPacketMeanCenter.doubleValue()) && 
				(varXCenter.doubleValue() == oldVarXCenter.doubleValue()) && 
				(varYCenter.doubleValue()==oldVarYCenter.doubleValue()) && 
				(varZCenter.doubleValue()==oldVarZCenter.doubleValue())){
			
			fileLogger.debug("SameCenter: TRUE" );
			return true;			
		}
		
		fileLogger.debug("SameCenter: FALSE" );
		
		return false;
	}
	
	public CentroidsEnum getInitType() {
		return initType;
	}


	public double getVarXCenter() {
		return varXCenter;
	}


	public void setVarXCenter(double varXCenter) {
		this.varXCenter = varXCenter;
	}


	public double getVarYCenter() {
		return varYCenter;
	}


	public void setVarYCenter(double varYCenter) {
		this.varYCenter = varYCenter;
	}


	public double getVarZCenter() {
		return varZCenter;
	}


	public void setVarZCenter(double varZCenter) {
		this.varZCenter = varZCenter;
	}


	public double getPacketMeanCenter() {
		return packetMeanCenter;
	}


	public void setPacketMeanCenter(double packetMeanCenter) {
		this.packetMeanCenter = packetMeanCenter;
	}
	
	
	private void setAllParameters(double packetMeanCenter, double varXCenter, 
			double varYCenter, double varZCenter){
		
		
		fileLogger.debug("Setting All Parameters: " + this.initType);
		
		
		this.packetMeanCenter = packetMeanCenter;
		this.varXCenter = varXCenter;
		this.varYCenter = varYCenter;
		this.varZCenter = varZCenter;
		
		//set the value the same for oldCenters
		this.oldPacketMeanCenter = this.packetMeanCenter.doubleValue();
		this.oldVarXCenter = this.varXCenter.doubleValue();
		this.oldVarYCenter = this.varYCenter.doubleValue();
		this.oldVarZCenter = this.varZCenter.doubleValue();
		
		fileLogger.debug("Center: " + toString());
		fileLogger.info("OLD_Center: " + toString());
	}


	public Vector<AccelerationPaquet> getMotionSamples() {
		return motionSamples;
	}


	public void setMotionSamples(Vector<AccelerationPaquet> motionSamples) {
		this.motionSamples = (Vector<AccelerationPaquet>) motionSamples.clone();
	}
	
	public void addMotionSample(AccelerationPaquet motionSample){
		this.motionSamples.add(motionSample);
	}
	
	public String toString(){		
		return "Type: " + initType + " PacKet_Mean_Center: " + packetMeanCenter + " Var_X_Center: " + varXCenter + 
		" Var_Y_Center: " + varYCenter + " Var_Z_Center: " + varZCenter;		
	}

}
